package cn.com.oidreams.common.utils;

import cn.com.oidreams.aliyun.robot.entity.BaseException;
import cn.com.oidreams.common.annotations.Required;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/***
 ** @category 反射工具类
 ** @author qing.yunhui
 ** @email: qingyh@glodon.com
 ** @createTime: 2021-11-26 10:38
 **/
public class ReflectUtil {

    /**
     * <p>验证对象是否通过验证</p>
     * @param object 待验证的对象
     * @return
     * */
    public static boolean isRequiredPass(Object object) throws Exception {
        Class<?> clz = object.getClass();
        Map<String, Field> fieldMap = getClassField(clz);
        Iterator<Field> iterator = fieldMap.values().iterator();
        while(iterator.hasNext()){
            Field field =  iterator.next();
            Required required = field.getAnnotation(Required.class);
            if(null==required){ continue; }
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), clz);
            Method method = propertyDescriptor.getReadMethod();
            Object value = method.invoke(object);
            if(StringUtil.isEmptys(value)){
                String errorMessage = required.errorMsg();
                errorMessage = StringUtil.isEmptys(errorMessage)?String.format("%s为必填参数!",field.getName()):errorMessage;
                throw new BaseException(errorMessage);
            }
            boolean parse = required.classParse();
            // 如果注解中的 classParse 不为 true，则不进行解释
            if(!parse){ continue; }
            boolean _primitive = isPrimitive(field.getDeclaringClass());
            // 如果是基本类型或包装类型则不进行解释
            if(_primitive){continue;}

            Map<String, Field> _map = getClassField(value.getClass());

            boolean pass = isRequiredPass(value);   // TODO 这里递归有bug ....
            if(!pass){ return Boolean.FALSE; }
        }
        return true;
    }

    public static boolean checkField(Object object,Field field) throws Exception {
        Required required = field.getAnnotation(Required.class);
        if(null==required){ return Boolean.TRUE; }
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), object.getClass());
        Method method = propertyDescriptor.getReadMethod();
        Object value = method.invoke(object);
        if(StringUtil.isEmptys(value)){
            String errorMessage = required.errorMsg();
            errorMessage = StringUtil.isEmptys(errorMessage)?String.format("%s为必填参数!",field.getName()):errorMessage;
            throw new BaseException(errorMessage);
        }
        boolean parse = required.classParse();
        // 如果注解中的 classParse 不为 true，则不进行解释
        if(!parse){ return Boolean.TRUE; }
        boolean _primitive = isPrimitive(field.getDeclaringClass());
        // 如果是基本类型或包装类型则不进行解释
        if(_primitive){return Boolean.TRUE;}
        Map<String, Field> map = getClassField(value.getClass());
        Iterator<Field> iterator = map.values().iterator();
        while(iterator.hasNext()){
            Field _field = iterator.next();

        }
        // todo
        return Boolean.FALSE;


    }


    /**
     * <p>判断类型是否是基本类型或包装类型</p>
     * @param _class
     * @return
     * */
    public static boolean isPrimitive(Class<?> _class){
        boolean _primitive = _class.isPrimitive();// 基本类型校验
        if(_primitive){return Boolean.TRUE;}
        try {
            return ((Class<?>)(_class.getField("TYPE").get(null))).isPrimitive();// 包装类型校验
        }catch (Exception e){
            return Boolean.FALSE;
        }
    }

    /**
     * 过滤不需要属性
     * @param field
     * @return
     */
    public static boolean needFilterField(Field field){
        // 过滤静态属性
        if(Modifier.isStatic(field.getModifiers())){ return true; }
        // 过滤transient 关键字修饰的属性
        if(Modifier.isTransient(field.getModifiers())){ return true; }
        return false;
    }


    /**
     * <p>获取当前类及其所有父类的所有公共声明的字段集(过滤静态属性及transient关键字修饰的属性)</p>
     * @param clazz
     * @return
     * */
    public static Map<String, Field> getClassField(Class<?> clazz){
        if(null==clazz){return null;}
        Map<String, Field> fieldMap = new HashMap<>();
        Field[] fieldList = clazz.getDeclaredFields();
        for(Field field:fieldList){
            if (ReflectUtil.needFilterField(field)) { continue; }
            fieldMap.put(field.getName(), field);
        }
        getSupperClassField(clazz,fieldMap);
        return fieldMap;
    }

    /**
     * <p>获取当前类的所有父类的所有公共声明的字段集(过滤静态属性及transient关键字修饰的属性)</p>
     * @param clazz
     * @param fieldMap
     * */
    private static void getSupperClassField(Class<?> clazz,Map<String, Field> fieldMap){
        if(null==clazz){return ;}
        Class<?> superClazz = clazz.getSuperclass();
        if (superClazz != null) {
            Field[] superFields = superClazz.getDeclaredFields();
            for(Field field : superFields){
                if (ReflectUtil.needFilterField(field)) { continue; }
                fieldMap.put(field.getName(), field);
            }
            getSupperClassField(superClazz, fieldMap);
        }
    }
}
